home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint110s / procfs.c < prev    next >
C/C++ Source or Header  |  1994-02-15  |  18KB  |  744 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1992,1993,1994 Atari Corporation.
  4. All rights reserved.
  5.  */
  6.  
  7. /* PROC pseudo-filesystem routines */
  8. /* basically just to allow 'ls -l X:' to give a list of active processes
  9.  * some things to note:
  10.  * process names are given as name.XXX, where 'XXX' is the pid of the
  11.  *   process
  12.  * process attributes depend on the run queue as follows:
  13.  *   RUNNING:    0x00        (normal)
  14.  *   READY:    0x01        (read-only)
  15.  *   WAIT:    0x20        (archive bit)
  16.  *   IOBOUND:    0x21        (archive bit+read-only)
  17.  *   ZOMBIE:    0x22        (archive+hidden)
  18.  *   TSR:    0x02        (hidden)
  19.  *   STOP:    0x24        (archive bit+system)
  20.  * the general principle is: inactive processes have the archive bit (0x20)
  21.  * set, terminated processes have the hidden bit (0x02) set, stopped processes
  22.  * have the system bit (0x04) set, and the read-only bit is used to
  23.  * otherwise distinguish states (which is unfortunate, since it would be
  24.  * nice if this bit corresponded with file permissions).
  25.  */
  26.  
  27. #include "mint.h"
  28.  
  29.  
  30. static long    ARGS_ON_STACK proc_root    P_((int drv, fcookie *fc));
  31. static long    ARGS_ON_STACK proc_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  32. static long    ARGS_ON_STACK proc_getxattr    P_((fcookie *fc, XATTR *xattr));
  33. static long    ARGS_ON_STACK proc_chattr    P_((fcookie *fc, int attrib));
  34. static long    ARGS_ON_STACK proc_chown    P_((fcookie *fc, int uid, int gid));
  35. static long    ARGS_ON_STACK proc_chmode    P_((fcookie *fc, unsigned mode));
  36. static long    ARGS_ON_STACK proc_rmdir    P_((fcookie *dir, const char *name));
  37. static long    ARGS_ON_STACK proc_remove    P_((fcookie *dir, const char *name));
  38. static long    ARGS_ON_STACK proc_getname    P_((fcookie *root, fcookie *dir, char *pathname,
  39.                             int size));
  40. static long    ARGS_ON_STACK proc_rename    P_((fcookie *olddir, char *oldname,
  41.                     fcookie *newdir, const char *newname));
  42. static long    ARGS_ON_STACK proc_opendir    P_((DIR *dirh, int flags));
  43. static long    ARGS_ON_STACK proc_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  44. static long    ARGS_ON_STACK proc_rewinddir    P_((DIR *dirh));
  45. static long    ARGS_ON_STACK proc_closedir    P_((DIR *dirh));
  46. static long    ARGS_ON_STACK proc_pathconf    P_((fcookie *dir, int which));
  47. static long    ARGS_ON_STACK proc_dfree    P_((fcookie *dir, long *buf));
  48. static DEVDRV *    ARGS_ON_STACK proc_getdev    P_((fcookie *fc, long *devsp));
  49.  
  50. static long    ARGS_ON_STACK proc_open    P_((FILEPTR *f));
  51. static long    ARGS_ON_STACK proc_write    P_((FILEPTR *f, const char *buf, long bytes));
  52. static long    ARGS_ON_STACK proc_read    P_((FILEPTR *f, char *buf, long bytes));
  53. static long    ARGS_ON_STACK proc_lseek    P_((FILEPTR *f, long where, int whence));
  54. static long    ARGS_ON_STACK proc_ioctl    P_((FILEPTR *f, int mode, void *buf));
  55. static long    ARGS_ON_STACK proc_datime    P_((FILEPTR *f, short *time, int rwflag));
  56. static long    ARGS_ON_STACK proc_close    P_((FILEPTR *f, int pid));
  57.  
  58. /* dummy routines from biosfs.c */
  59. extern long    ARGS_ON_STACK null_select    P_((FILEPTR *f, long p, int mode));
  60. extern void    ARGS_ON_STACK null_unselect    P_((FILEPTR *f, long p, int mode));
  61.  
  62. static PROC *    name2proc    P_((const char *name));
  63.  
  64.  
  65. DEVDRV proc_device = {
  66.     proc_open, proc_write, proc_read, proc_lseek, proc_ioctl, proc_datime,
  67.     proc_close, null_select, null_unselect
  68. };
  69.  
  70. FILESYS proc_filesys = {
  71.     (FILESYS *)0,
  72.     0,
  73.     proc_root,
  74.     proc_lookup, nocreat, proc_getdev, proc_getxattr,
  75.     proc_chattr, proc_chown, proc_chmode,
  76.     nomkdir, proc_rmdir, proc_remove, proc_getname, proc_rename,
  77.     proc_opendir, proc_readdir, proc_rewinddir, proc_closedir,
  78.     proc_pathconf, proc_dfree,
  79.     nowritelabel, noreadlabel, nosymlink, noreadlink, nohardlink,
  80.     nofscntl, nodskchng
  81. };
  82.  
  83. long ARGS_ON_STACK 
  84. proc_root(drv, fc)
  85.     int drv;
  86.     fcookie *fc;
  87. {
  88.     if (drv == PROCDRV) {
  89.         fc->fs = &proc_filesys;
  90.         fc->dev = drv;
  91.         fc->index = 0L;
  92.         return 0;
  93.     }
  94.     fc->fs = 0;
  95.     return EINTRN;
  96. }
  97.  
  98. static PROC *
  99. name2proc(name)
  100.     const char *name;
  101. {
  102.     const char *pstr;
  103.     char c;
  104.     int i;
  105.  
  106.     pstr = name;
  107.     while ( (c = *name++) != 0) {
  108.         if (c == '.')
  109.             pstr = name;
  110.     }
  111.     if (!isdigit(*pstr) && *pstr != '-')
  112.         return 0;
  113.     i = (int)atol(pstr);
  114.     if (i == -1)
  115.         return curproc;
  116.     else if (i == -2)
  117.         i = curproc->ppid;
  118.     return pid2proc(i);
  119. }
  120.  
  121. static long ARGS_ON_STACK 
  122. proc_lookup(dir, name, fc)
  123.     fcookie *dir;
  124.     const char *name;
  125.     fcookie *fc;
  126. {
  127.     PROC *p;
  128.  
  129.     if (dir->index != 0) {
  130.         DEBUG(("proc_lookup: bad directory"));
  131.         return EPTHNF;
  132.     }
  133.  
  134. /* special case: an empty name in a directory means that directory */
  135. /* so does "." */
  136.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  137.         *fc = *dir;
  138.         return 0;
  139.     }
  140.  
  141. /* another special case: ".." could be a mount point */
  142.     if (!strcmp(name, "..")) {
  143.         *fc = *dir;
  144.         return EMOUNT;
  145.     }
  146.  
  147.     if (0 == (p = name2proc(name))) {
  148.         DEBUG(("proc_lookup: name not found"));
  149.         return EFILNF;
  150.     } else {
  151.         fc->index = (long)p;
  152.         fc->fs = &proc_filesys;
  153.         fc->dev = PROC_RDEV_BASE | p->pid;
  154.     }
  155.     return 0;
  156. }
  157.  
  158. static int p_attr[NUM_QUEUES] = {    /* attributes corresponding to queues */
  159.     0,            /* "RUNNING" */
  160.     0x01,            /* "READY" */
  161.     0x20,            /* "WAITING" */
  162.     0x21,            /* "IOBOUND" */
  163.     0x22,            /* "ZOMBIE" */
  164.     0x02,            /* "TSR" */
  165.     0x24,            /* "STOPPED" */
  166.     0x21            /* "SELECT" (same as IOBOUND) */
  167. };
  168.  
  169. static long ARGS_ON_STACK 
  170. proc_getxattr(fc, xattr)
  171.     fcookie *fc;
  172.     XATTR *xattr;
  173. {
  174.     PROC *p;
  175.     extern int proctime, procdate;    /* see dosmem.c */
  176.  
  177.     xattr->blksize = 1;
  178.     if (fc->index == 0) {
  179.         /* the root directory */
  180.         xattr->index = 0;
  181.         xattr->dev = xattr->rdev = PROCDRV;
  182.         xattr->nlink = 1;
  183.         xattr->uid = xattr->gid = 0;
  184.         xattr->size = xattr->nblocks = 0;
  185.         xattr->mtime = xattr->atime = xattr->ctime = proctime;
  186.         xattr->mdate = xattr->adate = xattr->cdate = procdate;
  187.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  188.         xattr->attr = FA_DIR;
  189.         return 0;
  190.     }
  191.  
  192.     p = (PROC *)fc->index;
  193.     xattr->index = p->pid;
  194.     xattr->dev = xattr->rdev = PROC_RDEV_BASE | p->pid;
  195.     xattr->nlink = 1;
  196.     xattr->uid = p->ruid; xattr->gid = p->rgid;
  197.     xattr->size = xattr->nblocks = memused(p);
  198.     xattr->mtime = xattr->ctime = xattr->atime = p->starttime;
  199.     xattr->mdate = xattr->cdate = xattr->adate = p->startdate;
  200.     xattr->mode = S_IMEM | S_IRUSR | S_IWUSR;
  201.     xattr->attr = p_attr[p->wait_q];
  202.     return 0;
  203. }
  204.  
  205. static long ARGS_ON_STACK 
  206. proc_chattr(fc, attrib)
  207.     fcookie *fc;
  208.     int attrib;
  209. {
  210.     UNUSED(fc); UNUSED(attrib);
  211.  
  212.     return EACCDN;
  213. }
  214.  
  215. static long ARGS_ON_STACK 
  216. proc_chown(fc, uid, gid)
  217.     fcookie *fc;
  218.     int uid, gid;
  219. {
  220.     UNUSED(fc); UNUSED(uid); UNUSED(gid);
  221.     return EINVFN;
  222. }
  223.  
  224. static long ARGS_ON_STACK 
  225. proc_chmode(fc, mode)
  226.     fcookie *fc;
  227.     unsigned mode;
  228. {
  229.     UNUSED(fc); UNUSED(mode);
  230.     return EINVFN;
  231. }
  232.  
  233. static long ARGS_ON_STACK 
  234. proc_rmdir(dir, name)
  235.     fcookie *dir;
  236.     const char *name;
  237. {
  238.     UNUSED(dir); UNUSED(name);
  239.     return EPTHNF;
  240. }
  241.  
  242. static long ARGS_ON_STACK 
  243. proc_remove(dir, name)
  244.     fcookie *dir;
  245.     const char *name;
  246. {
  247.     PROC *p;
  248.  
  249.     if (dir->index != 0)
  250.         return EPTHNF;
  251.     p = name2proc(name);
  252.     if (!p)
  253.         return EFILNF;
  254.  
  255. /* this check is necessary because the Fdelete code checks for
  256.  * write permission on the directory, not on individual
  257.  * files
  258.  */
  259.     if (curproc->euid && curproc->ruid != p->ruid) {
  260.         DEBUG(("proc_remove: wrong user"));
  261.         return EACCDN;
  262.     }
  263.     post_sig(p, SIGTERM);
  264.     check_sigs();        /* it might have been us */
  265.     return 0;
  266. }
  267.  
  268. static long ARGS_ON_STACK 
  269. proc_getname(root, dir, pathname, size)
  270.     fcookie *root, *dir; char *pathname;
  271.     int size;
  272. {
  273.     PROC *p;
  274.  
  275.     UNUSED(root);
  276. /* BUG: we ought to look at size */
  277.     UNUSED(size);
  278.  
  279.     if (dir->index == 0)
  280.         *pathname = 0;
  281.     else {
  282.         p = (PROC *)dir->index;
  283.         ksprintf(pathname, "%s.03d", p->name, p->pid);
  284.     }
  285.     return 0;
  286. }
  287.  
  288. static long ARGS_ON_STACK 
  289. proc_rename(olddir, oldname, newdir, newname)
  290.     fcookie *olddir;
  291.     char *oldname;
  292.     fcookie *newdir;
  293.     const char *newname;
  294. {
  295.     PROC *p;
  296.     int i;
  297.  
  298.     if (olddir->index != 0 || newdir->index != 0)
  299.         return EPTHNF;
  300.     if ((p = name2proc(oldname)) == 0)
  301.         return EFILNF;
  302.  
  303.     oldname = p->name;
  304.     for (i = 0; i < PNAMSIZ; i++) {
  305.         if (*newname == 0 || *newname == '.') {
  306.             *oldname = 0; break;
  307.         }
  308.         *oldname++ = *newname++;
  309.     }
  310.     return 0;
  311. }
  312.  
  313. static long ARGS_ON_STACK 
  314. proc_opendir(dirh, flags)
  315.     DIR *dirh;
  316.     int flags;
  317. {
  318.     UNUSED(flags);
  319.  
  320.     dirh->index = 0;
  321.     return 0;
  322. }
  323.  
  324. static long ARGS_ON_STACK 
  325. proc_readdir(dirh, name, namelen, fc)
  326.     DIR *dirh;
  327.     char *name;
  328.     int namelen;
  329.     fcookie *fc;
  330. {
  331.     int i;
  332.     int giveindex = (dirh->flags == 0);
  333.     PROC *p;
  334.  
  335.     do {
  336.         i = dirh->index++;
  337. /* BUG: we shouldn't have the magic number "1000" for maximum proc pid */
  338.         if (i >= 1000) {
  339.             p = 0;
  340.             break;
  341.         }
  342.         p = pid2proc(i);
  343.     } while (!p);
  344.  
  345.     if (!p)
  346.         return ENMFIL;
  347.  
  348.     fc->index = (long)p;
  349.     fc->fs = &proc_filesys;
  350.     fc->dev = PROC_RDEV_BASE | p->pid;
  351.  
  352.     if (giveindex) {
  353.         namelen -= (int)sizeof(long);
  354.         if (namelen <= 0) return ERANGE;
  355.         *((long *)name) = (long)p->pid;
  356.         name += sizeof(long);
  357.     }
  358.     if (namelen < strlen(p->name) + 5)
  359.         return ENAMETOOLONG;
  360.  
  361.     ksprintf(name, "%s.%03d", p->name, p->pid);
  362.     return 0;
  363. }
  364.  
  365. static long ARGS_ON_STACK 
  366. proc_rewinddir(dirh)
  367.     DIR *dirh;
  368. {
  369.     dirh->index = 0;
  370.     return 0;
  371. }
  372.  
  373. static long ARGS_ON_STACK 
  374. proc_closedir(dirh)
  375.     DIR *dirh;
  376. {
  377.     UNUSED(dirh);
  378.     return 0;
  379. }
  380. static long ARGS_ON_STACK 
  381. proc_pathconf(dir, which)
  382.     fcookie *dir;
  383.     int which;
  384. {
  385.     UNUSED(dir);
  386.  
  387.     switch(which) {
  388.     case -1:
  389.         return DP_MAXREQ;
  390.     case DP_IOPEN:
  391.         return UNLIMITED;    /* no internal limit on open files */
  392.     case DP_MAXLINKS:
  393.         return 1;        /* we don't have hard links */
  394.     case DP_PATHMAX:
  395.         return PATH_MAX;    /* max. path length */
  396.     case DP_NAMEMAX:
  397.         return PNAMSIZ + 4;    /* max. length of individual name */
  398.                     /* the "+4" is for the pid: ".123" */
  399.     case DP_ATOMIC:
  400.         return UNLIMITED;    /* all writes are atomic */
  401.     case DP_TRUNC:
  402.         return DP_DOSTRUNC;    /* file names are truncated to 8.3 */
  403.     case DP_CASE:
  404.         return DP_CASEINSENS;    /* case preserved, but ignored */
  405.     default:
  406.         return EINVFN;
  407.     }
  408. }
  409.  
  410. static long ARGS_ON_STACK 
  411. proc_dfree(dir, buf)
  412.     fcookie *dir;
  413.     long *buf;
  414. {
  415.     long size;
  416. /* "sector" size is the size of the smallest amount of memory that can be
  417.    allocated. see mem.h for the definition of ROUND
  418.  */
  419.     long secsiz = ROUND(1);
  420.  
  421.     UNUSED(dir);
  422.  
  423.     size = tot_rsize(core, 0) + tot_rsize(alt, 0);
  424.     *buf++ = size/secsiz;            /* number of free clusters */
  425.     size = tot_rsize(core, 1) + tot_rsize(alt, 1);
  426.     *buf++ = size/secsiz;            /* total number of clusters */
  427.     *buf++ = secsiz;            /* sector size (bytes) */
  428.     *buf = 1;                /* cluster size (in sectors) */
  429.     return 0;
  430. }
  431.  
  432. static DEVDRV * ARGS_ON_STACK 
  433. proc_getdev(fc, devsp)
  434.     fcookie *fc;
  435.     long *devsp;
  436. {
  437.     PROC *p;
  438.  
  439.     p = (PROC *)fc->index;
  440.  
  441.     *devsp = (long)p;
  442.     return &proc_device;
  443. }
  444.  
  445. /*
  446.  * PROC device driver
  447.  */
  448.  
  449. /*
  450.  * BUG: file locking and the O_SHMODE restrictions are not implemented
  451.  * for processes
  452.  */
  453.  
  454. static long ARGS_ON_STACK 
  455. proc_open(f)
  456.     FILEPTR *f;
  457. {
  458.     UNUSED(f);
  459.  
  460.     return 0;
  461. }
  462.  
  463. static long ARGS_ON_STACK 
  464. proc_write(f, buf, nbytes)
  465.     FILEPTR *f; const char *buf; long nbytes;
  466. {
  467.     PROC *p = (PROC *)f->devinfo;
  468.     char *where;
  469.     long bytes_written = 0;
  470.     int prot_hold;
  471.  
  472.     where = (char *)f->pos;
  473.  
  474. TRACE(("proc_write to pid %d: %ld bytes to %lx", p->pid, nbytes, where));
  475.  
  476.     prot_hold = mem_access_for(p, (ulong)where,nbytes);
  477.     if (prot_hold == 0) {
  478.         DEBUG(("Can't Fwrite that memory: not all the same or not owner."));
  479.         return EACCDN;
  480.     }
  481.     if (prot_hold == 1) {
  482.         DEBUG(("Attempt to Fwrite memory crossing a managed boundary"));
  483.         return EACCDN;
  484.     }
  485.  
  486.     bytes_written = nbytes;
  487.     while (nbytes-- > 0) {
  488.         *where++ = *buf++;
  489.     }
  490.     cpush((void *)f->pos, bytes_written);    /* flush cached data */
  491.  
  492.     /* MEMPROT: done with temp mapping (only call if temp'ed above) */
  493.     if (prot_hold != -1) prot_temp((ulong)f->pos,bytes_written,prot_hold);
  494.  
  495.     f->pos += bytes_written;
  496.     return bytes_written;
  497. }
  498.  
  499. static long ARGS_ON_STACK 
  500. proc_read(f, buf, nbytes)
  501.     FILEPTR *f; char *buf; long nbytes;
  502. {
  503.     PROC *p = (PROC *)f->devinfo;
  504.     char *where;
  505.     long bytes_read = 0;
  506.     int prot_hold;
  507.  
  508.     where = (char *)f->pos;
  509.  
  510. TRACE(("proc_read from pid %d: %ld bytes from %lx", p->pid, nbytes, where));
  511.  
  512.     prot_hold = mem_access_for(p, (ulong)where,nbytes);
  513.     if (prot_hold == 0) {
  514.         DEBUG(("Can't Fread that memory: not all the same."));
  515.         return EACCDN;
  516.     }
  517.     if (prot_hold == 1) {
  518.         DEBUG(("Attempt to Fread memory crossing a managed boundary"));
  519.         return EACCDN;
  520.     }
  521.  
  522.     bytes_read = nbytes;
  523.     while (nbytes-- > 0) {
  524.         *buf++ = *where++;
  525.     }
  526.  
  527.     /* MEMPROT: done with temp mapping (only call if temp'ed above) */
  528.     if (prot_hold != -1) prot_temp((ulong)f->pos,bytes_read,prot_hold);
  529.  
  530.     f->pos += bytes_read;
  531.     return bytes_read;
  532. }
  533.  
  534. /*
  535.  * proc_ioctl: currently, the only IOCTL's available are:
  536.  * PPROCADDR: get address of PROC structure's "interesting" bits
  537.  * PCTXTSIZE: get the size of the CONTEXT structure
  538.  * PBASEADDR: get address of process basepage
  539.  * PSETFLAGS: set the memory allocation flags (e.g. to malloc from fastram)
  540.  * PGETFLAGS: get the memory allocation flags
  541.  * PTRACESFLAGS: set the process tracing flags
  542.  * PTRACEGFLAGS: get the process tracing flags
  543.  * PTRACEGO: restart the process (T1=0/T1=0)
  544.  * PTRACEFLOW: restart the process (T1=0/T0=1)
  545.  * PTRACESTEP: restart the process (T1=1/T0=0)
  546.  * PTRACE11: restart the process (T1=1/T0=1)
  547.  * PLOADINFO: get information about the process name and command line
  548.  */
  549.  
  550. static long ARGS_ON_STACK 
  551. proc_ioctl(f, mode, buf)
  552.     FILEPTR *f; int mode; void *buf;
  553. {
  554.     PROC *p;
  555.     extern long mcpu;    /* in main.c */
  556.     short sr;
  557.  
  558.     p = (PROC *)f->devinfo;
  559.     switch(mode) {
  560.     case PPROCADDR:
  561.         *((long *)buf) = (long)&p->magic;
  562.         return 0;
  563.     case PBASEADDR:
  564.         if (p == rootproc)
  565.             *((long *)buf) = (long)_base;
  566.         else
  567.             *((long *)buf) = (long)p->base;
  568.         return 0;
  569.     case PCTXTSIZE:
  570.         *((long *)buf) = sizeof(CONTEXT);
  571.         return 0;
  572.     case PFSTAT:
  573.         {
  574.         FILEPTR *pf;
  575.         int pfd = (*(ushort *)buf);
  576.         if (pfd < MIN_HANDLE || pfd >= MAX_OPEN ||
  577.             !(pf = p->handle[pfd]))
  578.             return EIHNDL;
  579.         return (*pf->fc.fs->getxattr)(&pf->fc, (XATTR *)buf);
  580.         }
  581.     case PSETFLAGS:
  582.         {
  583.         int newflags = (ushort)(*(long *)buf);
  584.         if ((newflags & F_OS_SPECIAL) &&
  585.             (!(p->memflags & F_OS_SPECIAL))) {
  586.             /* you're making the process OS_SPECIAL */
  587.             TRACE(("Fcntl OS_SPECIAL pid %d",p->pid));
  588.             p->memflags = newflags;
  589.             mem_prot_special(p);
  590.         }
  591.         /* note: only the low 16 bits are actually used */
  592.         p->memflags = *((long *)buf);
  593.         return 0;
  594.         }
  595.     case PGETFLAGS:
  596.         *((long *)buf) = p->memflags;
  597.         return 0;
  598.     case PTRACESFLAGS:
  599.         if (p->ptracer == curproc || p->ptracer == 0) {
  600.             p->ptraceflags = *(ushort *)buf;
  601.             if (p->ptraceflags == 0) {
  602.                 p->ptracer = 0;
  603.                 p->ctxt[CURRENT].ptrace = 0;
  604.                 p->ctxt[SYSCALL].ptrace = 0;
  605.         /* if the process is stopped, restart it */
  606.                 if (p->wait_q == STOP_Q) {
  607.                     p->sigpending &= ~STOPSIGS;
  608.                     post_sig(p, SIGCONT);
  609.                 }
  610.             } else if (p == curproc) {
  611.                 p->ptracer = pid2proc(p->ppid);
  612.             } else {
  613.                 p->ptracer = curproc;
  614.             }
  615.         } else {
  616.             DEBUG(("proc_ioctl: process already being traced"));
  617.             return EACCDN;
  618.         }
  619.         return 0;
  620.     case PTRACEGFLAGS:
  621.         if (p->ptracer == curproc) {
  622.             *(ushort *)buf = p->ptraceflags;
  623.             return 0;
  624.         } else {
  625.             return EACCDN;
  626.         }
  627.     case PTRACE11:
  628.         return EINVFN;
  629.     case PTRACEFLOW:
  630.         if (mcpu < 20) {
  631.             DEBUG(("proc_ioctl: wrong processor"));
  632.             return EINVFN;
  633.         }
  634.         /* fall through */
  635.     case PTRACEGO:
  636.     case PTRACESTEP:
  637.         if (!p->ptracer) {
  638.             DEBUG(("proc_ioctl(PTRACE): process not being traced"));
  639.             return EACCDN;
  640.         }
  641.         else if (p->wait_q != STOP_Q) {
  642.             DEBUG(("proc_ioctl(PTRACE): process not stopped"));
  643.             return EACCDN;
  644.         }
  645.         else if (p->wait_cond &&
  646.             (1L << ((p->wait_cond >> 8) & 0x1f)) & STOPSIGS) {
  647.             DEBUG(("proc_ioctl(PTRACE): process stopped by job control"));
  648.             return EACCDN;
  649.         }
  650.         if (buf && *(ushort *)buf >= NSIG) {
  651.             DEBUG(("proc_ioctl(PTRACE): illegal signal number"));
  652.             return ERANGE;
  653.         }
  654.         p->ctxt[SYSCALL].sr &= 0x3fff;    /* clear both trace bits */
  655.         p->ctxt[SYSCALL].sr |= (mode - PTRACEGO) << 14;
  656.         p->sigpending = 0;
  657.         if (buf && *(ushort *)buf != 0) {
  658. TRACE(("PTRACEGO: sending signal %d to pid %d", *(ushort *)buf, p->pid));
  659.             post_sig(p, *(ushort *)buf);
  660.  
  661. /* another SIGNULL hack... within check_sigs() we watch for a pending
  662.  * SIGNULL, if we see this then we allow delivery of a signal to the
  663.  * process, rather than telling the parent.
  664.  */
  665.             p->sigpending |= 1L;
  666.         } else {
  667. TRACE(("PTRACEGO: no signal"));
  668.         }
  669. /* wake the process up */
  670.         sr = spl7();
  671.         rm_q(p->wait_q, p);
  672.         add_q(READY_Q, p);
  673.         spl(sr);
  674.         return 0;
  675.     /* jr: PLOADINFO returns information about params passed to Pexec */
  676.     case PLOADINFO:
  677.         {
  678.             struct ploadinfo *pl = buf;
  679.  
  680.             if (!p->fname[0]) return EFILNF;
  681.             strncpy (pl->cmdlin, p->cmdlin, 128);
  682.             if (strlen (p->fname) <= pl->fnamelen)
  683.                 strcpy (pl->fname, p->fname);
  684.             else
  685.                 return ENAMETOOLONG;
  686.         }
  687.         return 0;
  688.  
  689.     case FIONREAD:
  690.     case FIONWRITE:
  691.         *((long *)buf) = 1L;    /* we're always ready for i/o */
  692.         return 0;
  693.     default:
  694.         DEBUG(("procfs: bad Fcntl command"));
  695.     }
  696.     return EINVFN;
  697. }
  698.  
  699. static long ARGS_ON_STACK 
  700. proc_lseek(f, where, whence)
  701.     FILEPTR *f; long where; int whence;
  702. {
  703.     switch(whence) {
  704.     case 0:
  705.     case 2:
  706.         f->pos = where;
  707.         break;
  708.     case 1:
  709.         f->pos += where;
  710.         break;
  711.     default:
  712.         return EINVFN;
  713.     }
  714.     return f->pos;
  715. }
  716.  
  717. static long ARGS_ON_STACK 
  718. proc_datime(f, timeptr, rwflag)
  719.     FILEPTR *f;
  720.     short *timeptr;
  721.     int rwflag;
  722. {
  723.     PROC *p;
  724.  
  725.     p = (PROC *)f->devinfo;
  726.     if (rwflag) {
  727.         return EACCDN;
  728.     }
  729.     else {
  730.         *timeptr++ = p->starttime;
  731.         *timeptr = p->startdate;
  732.     }
  733.     return 0;
  734. }
  735.  
  736. static long ARGS_ON_STACK 
  737. proc_close(f, pid)
  738.     FILEPTR *f;
  739.     int pid;
  740. {
  741.     UNUSED(f); UNUSED(pid);
  742.     return 0;
  743. }
  744.